package com.ft.oa.service.project.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ft.oa.domain.check.ExecProjectExamine;
import com.ft.oa.domain.check.ExecProjectProblem;
import com.ft.oa.domain.dto.ApiResult;
import com.ft.oa.domain.dto.knowledgeBase.AttachmentDto;
import com.ft.oa.domain.project.ProjectWarranty;
import com.ft.oa.domain.project.ProjectWarrantyPage;
import com.ft.oa.domain.project.WarrantyReturnedMoney;
import com.ft.oa.domain.project.WarrantyReturnedRecord;
import com.ft.oa.enums.DirectoryTypeEnum;
import com.ft.oa.enums.ManagerEnum;
import com.ft.oa.enums.WarrantyStatus;
import com.ft.oa.mapper.attachment.AttachmentMapper;
import com.ft.oa.mapper.check.ExecProjectExamineMapper;
import com.ft.oa.mapper.check.ExecProjectProblemMapper;
import com.ft.oa.mapper.project.ProjectWarrantyMapper;
import com.ft.oa.mapper.project.WarrantyReturnedMoneyMapper;
import com.ft.oa.mapper.project.WarrantyReturnedRecordMapper;
import com.ft.oa.mapper.sys.SysUserMapper;
import com.ft.oa.service.knowledgeBase.DirectoryService;
import com.ft.oa.service.project.ExecProjectService;
import com.ft.oa.service.project.ProjectWarrantyService;
import com.ft.oa.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

/**
 * 项目质保管理
 * @author liyansheng
 * @ClassName ProjectWarrantyServiceImpl
 * @date 2022-1-14 10:03:26
 */
@Service
public class ProjectWarrantyServiceImpl implements ProjectWarrantyService {

    @Resource
    private ProjectWarrantyMapper projectWarrantyMapper;
    @Resource
    private AttachmentMapper attachmentMapper;
    @Resource
    private ExecProjectService execProjectService;
    @Resource
    private ExecProjectExamineMapper execProjectExamineMapper;
    @Resource
    private WarrantyReturnedMoneyMapper warrantyReturnedMoneyMapper;

    @Resource
    private WarrantyReturnedRecordMapper warrantyReturnedRecordMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private ExecProjectProblemMapper execProjectProblemMapper;

    @Resource
    private DirectoryService directoryService;

    /**
     * 质保项目列表查询
     * @Author liyansheng
     * @Time 2022-1-14 13:58:39
     * @param projectWarrantyPage
     * @return
     */
    @Override
    public ApiResult page(ProjectWarrantyPage projectWarrantyPage) {
        QueryWrapper<ProjectWarranty> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ManagerEnum.GENERAL.toString().equals(SecurityUtils.getCurrentUser().getManager()),ProjectWarranty::getCreator,SecurityUtils.getCurrentUser().getId())
                .like(StringUtils.hasText(projectWarrantyPage.getWarrantyName()),ProjectWarranty::getWarrantyName,projectWarrantyPage.getWarrantyName())
                .like(StringUtils.hasText(projectWarrantyPage.getProjectName()),ProjectWarranty::getProjectName,projectWarrantyPage.getProjectName());
        Page<ProjectWarranty> page = new Page<>(projectWarrantyPage.getPage(),projectWarrantyPage.getSize());
        IPage<ProjectWarranty> pages = projectWarrantyMapper.selectPage(page,queryWrapper);
        List<ProjectWarranty> records = pages.getRecords();
        records.forEach( e->{
            //统计质保次数
            QueryWrapper<WarrantyReturnedRecord> queryRecordWrapper = new QueryWrapper<>();
            queryRecordWrapper.lambda().eq(WarrantyReturnedRecord::getParentId,e.getId());
            e.setTimes(warrantyReturnedRecordMapper.selectCount(queryRecordWrapper));
            //统计汇款金额总数
            QueryWrapper<WarrantyReturnedMoney> WarrantyRecord = new QueryWrapper<>();
            WarrantyRecord.select("IFNULL(sum(returned_money),0.00)as returned_money,max(returned_date) as returned_date,count(1) as money_times,(select final_payment from warranty_returned_money ORDER BY create_time ASC LIMIT 1)  as final_payment")
                    .eq("parent_id",e.getId());
            List<WarrantyReturnedMoney> warrantyReturnedMonies = warrantyReturnedMoneyMapper.selectList(WarrantyRecord);
            warrantyReturnedMonies.forEach(money ->{
                //汇款总金额
                e.setTotalReturnAmount(money.getReturnedMoney().add(e.getTotalReturnAmount()));
                //回款日期
                e.setEstimatedDateOfPayment(money.getReturnedDate());
                //回款次数
                e.setMoneyTimes(money.getMoneyTimes());
                //剩余尾款
                e.setFinalPayment(money.getFinalPayment());
            });
            QueryWrapper<ExecProjectProblem> projectWrapper = new QueryWrapper<>();
            projectWrapper.lambda()
                    .eq(ExecProjectProblem::getExamineId,e.getExamineId())
                    .eq(ExecProjectProblem::getProblemState,"0");
            Integer integer = execProjectProblemMapper.selectCount(projectWrapper);
            /**
             * 是否有待问题解决
             */
            e.setProblemState(integer);
            // 质保负责人
            Integer qualityAssuranceOfficer = e.getQualityAssuranceOfficer();
            if(qualityAssuranceOfficer!=null){
                e.setQualityAssuranceOfficerName(sysUserMapper.selectById(e.getQualityAssuranceOfficer()).getNickname());
            }
            e.setWarrantyStatusName(WarrantyStatus.getByCode(e.getWarrantyStatus()));
        });
        return ApiResult.successWithData(pages);
    }

    /**
     * 新增质保项目
     * @Author liyansheng
     * @Time 2022-1-14 13:58:39
     * @param execProjectExamine
     * @return
     */
    @Override
    @Transactional
    public ApiResult add(ExecProjectExamine execProjectExamine) {
        //调用质保接口新增一条质保记录
        int insert = 0;
        if(execProjectExamine.getQuality()!=null&&execProjectExamine.getQuality()==1){
            ProjectWarranty projectWarranty = new ProjectWarranty();
            projectWarranty.setExamineId(execProjectExamine.getId());
            projectWarranty.setProjectNumber(execProjectExamine.getProjectNumber());
            projectWarranty.setWarrantyName(execProjectExamine.getProjectName());
            projectWarranty.setTotalReturnAmount(execProjectExamine.getReturnedMoney());
            projectWarranty.setTotalMoney(execProjectExamine.getTotalMoney());
            projectWarranty.setProjectName(execProjectExamine.getProjectName());
            //新增质保负责人
           if (execProjectExamine.getQuality()==1) {
               projectWarranty.setQualityAssuranceOfficer(execProjectExamine.getQualityAssuranceOfficer());
           }
               insert = projectWarrantyMapper.insert(projectWarranty);

        }
        return ApiResult.successWithData(insert);
    }

    /**
     * 新增质保回款  （每新增一条记录、在主表已回款中进行增加计算，方便后续计算未回款金额）
     * @Author liyansheng
     * @Time 2022-1-14 13:58:39
     * @param warrantyReturnedMoney
     * @return
     */
    @Override
    @Transactional
    public ApiResult addMoney(WarrantyReturnedMoney warrantyReturnedMoney) {
        //插入回款数据
        int insert = warrantyReturnedMoneyMapper.insert(warrantyReturnedMoney);
        return ApiResult.successWithData(insert);
    }

    /**
     * 新增质保记录
     * @Author liyansheng
     * @Time 2022-1-14 13:58:39
     * @param warrantyReturnedRecord
     * @return
     */
    @Override
    @Transactional
    public ApiResult addRecord(WarrantyReturnedRecord warrantyReturnedRecord) {
        List<AttachmentDto> attachments = warrantyReturnedRecord.getAttachments();
        if(attachments != null && attachments.size() > 0){
            String json = JSONArray.toJSONString(attachments);
            warrantyReturnedRecord.setAchment(json);
        }
        int insert = warrantyReturnedRecordMapper.insert(warrantyReturnedRecord);
        int warrantyResult = warrantyReturnedRecord.getWarrantyResult();
        LambdaUpdateChainWrapper<ExecProjectProblem> wrapper = new LambdaUpdateChainWrapper<>(execProjectProblemMapper);
        //如果问题已解决则进行更新问题表
        if(warrantyResult==0){
            wrapper.eq(ExecProjectProblem::getId,warrantyReturnedRecord.getExecid())
                    .set(ExecProjectProblem::getProblemState,"1")
                    .update();
        }else{
            //如果问题没有解决则记录问题描述
            wrapper.eq(ExecProjectProblem::getId,warrantyReturnedRecord.getExecid())
                    .set(ExecProjectProblem::getProblemDescr,warrantyReturnedRecord.getProblemMemo())
                    .update();
        }
        /**
         * 保存附件项目相关的公共方法
         *
         * @param attachments 附件集合
         * @param source      来源  根据 DirectoryTypeEnum
         * @param relationId  业务id
         * @param sourceId    如果一个表单有多个附件，用于标识附件属于表单的哪个附件
         * @param  projectNumber 项目编号 全局唯一
         */
        directoryService.saveProAttachment(attachments,DirectoryTypeEnum.PRO_PM_WARRANTY.getCode(),String.valueOf(warrantyReturnedRecord.getId()),"1",warrantyReturnedRecord.getProjectNumber());
        return ApiResult.successWithData(insert);
    }

    /**
     * 编辑质保项目
     * @Author liyansheng
     * @Time 2022-1-14 13:58:39
     * @param projectWarranty
     * @return
     */
    @Override
    @Transactional
    public ApiResult edit(ProjectWarranty projectWarranty) {
        Integer warrantyStatus = projectWarranty.getWarrantyStatus();
        if(warrantyStatus.equals(1)){
            LambdaUpdateChainWrapper<ExecProjectExamine> wrapper = new LambdaUpdateChainWrapper<>(execProjectExamineMapper);
            wrapper.eq(ExecProjectExamine::getProjectNumber,projectWarranty.getProjectNumber())
                    .set(ExecProjectExamine::getQuality,"1")
                    .update();
        }
        UpdateWrapper<ProjectWarranty> updateWrapper = new UpdateWrapper();
        updateWrapper.lambda()
                .eq(ProjectWarranty::getId,projectWarranty.getId())
                .set(ProjectWarranty::getUpdateTime,projectWarranty.getUpdateTime())
                .set(ProjectWarranty::getWarrantyName,projectWarranty.getWarrantyName())
                .set(ProjectWarranty::getQualityAssuranceOfficer,projectWarranty.getQualityAssuranceOfficer())
                .set(ProjectWarranty::getWarrantyStatus,projectWarranty.getWarrantyStatus())
                .set(ProjectWarranty::getStartDate,projectWarranty.getStartDate())
                .set(ProjectWarranty::getEndDate,projectWarranty.getEndDate())
        ;
        int update = projectWarrantyMapper.update(null, updateWrapper);
        return ApiResult.successWithData(update);
    }

    /**
     * 详情
     * @param id
     * @return
     */
    @Override
    public ApiResult detail(Long id) {
        HashMap<String,Object> resultMap = new HashMap<>();
        //查询主表数据
        ProjectWarranty projectWarranty = projectWarrantyMapper.selectById(id);
        //统计质保次数
        QueryWrapper<WarrantyReturnedRecord> queryRecordWrapper = new QueryWrapper<>();
        queryRecordWrapper.lambda().eq(WarrantyReturnedRecord::getParentId,projectWarranty.getId());
        projectWarranty.setTimes(warrantyReturnedRecordMapper.selectCount(queryRecordWrapper));
        //统计汇款金额总数
        QueryWrapper<WarrantyReturnedMoney> WarrantyRecord = new QueryWrapper<>();
        WarrantyRecord.select("IFNULL(sum(returned_money),0)as returned_money,max(returned_date) as returned_date,count(1) as money_times")
                .eq("parent_id",projectWarranty.getId());
        List<WarrantyReturnedMoney> warrantyReturnedMonies = warrantyReturnedMoneyMapper.selectList(WarrantyRecord.orderByDesc("id"));
        warrantyReturnedMonies.forEach(money ->{
            //汇款总金额
            projectWarranty.setTotalReturnAmount(money.getReturnedMoney().add(projectWarranty.getTotalReturnAmount()));
            //回款日期
            projectWarranty.setEstimatedDateOfPayment(money.getReturnedDate());
            //回款次数
            projectWarranty.setMoneyTimes(money.getMoneyTimes());
        });
        QueryWrapper<ExecProjectProblem> projectWrapper = new QueryWrapper<>();
        projectWrapper.lambda()
                .eq(ExecProjectProblem::getExamineId,projectWarranty.getExamineId())
                .eq(ExecProjectProblem::getProblemState,"0");
        Integer integer = execProjectProblemMapper.selectCount(projectWrapper);
        /**
         * 是否有待问题解决
         */
        projectWarranty.setProblemState(integer);
        // 质保负责人
        if( null!=projectWarranty.getQualityAssuranceOfficer()){
            projectWarranty.setQualityAssuranceOfficerName(sysUserMapper.selectById(projectWarranty.getQualityAssuranceOfficer()).getNickname());
        }
        projectWarranty.setWarrantyStatusName(WarrantyStatus.getByCode(projectWarranty.getWarrantyStatus()));
        resultMap.put("projectWarranty",projectWarranty);
        //查询回款记录
        QueryWrapper<WarrantyReturnedMoney> queryMoneyWrapper = new QueryWrapper<>();
        queryMoneyWrapper.lambda().eq(WarrantyReturnedMoney::getParentId,id);
        List<WarrantyReturnedMoney> warrantyReturnedMonie = warrantyReturnedMoneyMapper.selectList(queryMoneyWrapper);
        resultMap.put("warrantyReturnedMonies",warrantyReturnedMonie);
        //查询质保记录
        QueryWrapper<WarrantyReturnedRecord> queryRecordWrappe = new QueryWrapper<>();
        queryRecordWrapper.lambda().eq(WarrantyReturnedRecord::getParentId,projectWarranty.getId());
        List<WarrantyReturnedRecord> warrantyReturnedRecords = warrantyReturnedRecordMapper.selectList(queryRecordWrappe);
        warrantyReturnedRecords.forEach(e ->{
            String achment = e.getAchment();
            e.setAchment("");
            e.setAttachments(JSONObject.parseArray(achment, AttachmentDto.class));
        });
        resultMap.put("warrantyReturnedRecords",warrantyReturnedRecords);
        return ApiResult.successWithData(resultMap);
    }

    @Override
    public ApiResult execproblem(ProjectWarrantyPage projectWarrantyPage) {
        QueryWrapper<ExecProjectProblem> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ExecProjectProblem::getProblemState,"0")
                        .eq(ExecProjectProblem::getState,"0");
        if(projectWarrantyPage.getExaminid()!=null){
            wrapper.lambda().eq(ExecProjectProblem::getExamineId,projectWarrantyPage.getExaminid());
        }else{
            wrapper.lambda().eq(ExecProjectProblem::getExamineId,projectWarrantyPage.getId());
        }
        return ApiResult.successWithData(execProjectProblemMapper.selectList(wrapper));
    }

    @Override
    public ApiResult addmaintenance(ExecProjectProblem execProjectProblem) {
        int insert = 0;
        if(execProjectProblem.getExamineId()!=null){
             insert = execProjectProblemMapper.insert(execProjectProblem);
        }else{
            execProjectProblem.setExamineId(execProjectProblem.getExecid());
            insert = execProjectProblemMapper.insert(execProjectProblem);
        }
        return ApiResult.successWithData(insert);
    }
}
